/*
 *  Copyright (C) 2005-2007 Renier Roth
 *  www.renier.de
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package de.renier.jkeepass.components;

import java.awt.Color;
import java.awt.Component;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Date;

import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.ListSelectionModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

import de.renier.jkeepass.model.BasicElementTableModel;
import de.renier.jkeepass.renderer.SortHeaderRenderer;


/**
 * BasicElementTable
 *
 * @author <a href="mailto:software@renier.de">Renier Roth</a>
 */
public class BasicElementTable extends JTable implements MouseListener, JSortTable, Autoscroll {
 
  private static final long serialVersionUID = 6661964939889484183L;
  private static final Color EXPIRE_COLOR = Color.getHSBColor(0.57f, 0.12f, 0.96f);
  private Insets autoscrollInsets = new Insets(20, 20, 20, 20); // insets
  protected int sortedColumnIndex = -1;
  protected boolean sortedColumnAscending = true;
  
  public BasicElementTable() {
    setAutoscrolls(true);
    setModel(new BasicElementTableModel());
    getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    // create drag&Drop handler
    new BasicElementTableTransferHandler(this, DnDConstants.ACTION_MOVE);
    // init header for sorting
    initSortHeader();
  }

  /*
   * (non-Javadoc)
   * @see java.awt.dnd.Autoscroll#autoscroll(java.awt.Point)
   */
  public void autoscroll(Point cursorLocation) {
    Insets insets = getAutoscrollInsets();
    Rectangle outer = getVisibleRect();
    Rectangle inner = new Rectangle(outer.x+insets.left, outer.y+insets.top, outer.width-(insets.left+insets.right), outer.height-(insets.top+insets.bottom));
    if (!inner.contains(cursorLocation))  {
      Rectangle scrollRect = new Rectangle(cursorLocation.x-insets.left, cursorLocation.y-insets.top, insets.left+insets.right, insets.top+insets.bottom);
      scrollRectToVisible(scrollRect);
    }
  }

  /*
   * (non-Javadoc)
   * @see java.awt.dnd.Autoscroll#getAutoscrollInsets()
   */
  public Insets getAutoscrollInsets() {
    return autoscrollInsets;
  }
  
  /**
   * initSortHeader
   */
  protected void initSortHeader() {
    JTableHeader header = getTableHeader();
    header.setReorderingAllowed(false);
    header.setDefaultRenderer(new SortHeaderRenderer());
    header.addMouseListener(this);
  }
  
  /*
   * (non-Javadoc)
   * @see javax.swing.JTable#getScrollableTracksViewportHeight()
   */
  public boolean getScrollableTracksViewportHeight() {
    Component parent = getParent();
    if (parent instanceof JViewport)
      return parent.getHeight() > getPreferredSize().getHeight();
    return false;
  }  

  /*
   * (non-Javadoc)
   * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
   */
  public void mouseClicked(MouseEvent e) {  }
  public void mouseEntered(MouseEvent e) {  }
  public void mouseExited(MouseEvent e) {  }
  public void mousePressed(MouseEvent e) {  }
  public void mouseReleased(MouseEvent e) {
    TableColumnModel colModel = getColumnModel();
    int index = colModel.getColumnIndexAtX(e.getX());
    int modelIndex = colModel.getColumn(index).getModelIndex();
    BasicElementTableModel model = (BasicElementTableModel)getModel();
    if (model.isSortable(modelIndex)) {
      // toggle ascension, if already sorted
      if (sortedColumnIndex == index) {
        sortedColumnAscending = !sortedColumnAscending;
      }
      sortedColumnIndex = index;
      model.sortColumn(modelIndex, sortedColumnAscending);
      // refresh
      model.fireTableDataChanged();
      getTableHeader().repaint();
    }    
  }
  
  /*
   * (non-Javadoc)
   * @see de.renier.jkeepass.components.JSortTable#getSortedColumnIndex()
   */
  public int getSortedColumnIndex() {
    return sortedColumnIndex;
  }

  /*
   * (non-Javadoc)
   * @see de.renier.jkeepass.components.JSortTable#isSortedColumnAscending()
   */
  public boolean isSortedColumnAscending() {
    return sortedColumnAscending;
  }

  /* (non-Javadoc)
   * @see javax.swing.JTable#prepareRenderer(javax.swing.table.TableCellRenderer, int, int)
   */
  public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    return super.prepareRenderer(new HighlightTableRenderer(renderer), row, column);
  }
  
  /**
   * HighlightTableRenderer
   */
  private static class HighlightTableRenderer implements TableCellRenderer {
    
    TableCellRenderer renderer;
    
    public HighlightTableRenderer(TableCellRenderer renderer) {
      this.renderer = renderer;
    }

    /* (non-Javadoc)
     * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
     */
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      Component comp = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
      if (!isSelected) {
        Date date = (Date)table.getValueAt(row, 3);
        if (date != null && date.getTime() < System.currentTimeMillis()) {
          comp.setBackground(EXPIRE_COLOR);
        } else {
          comp.setBackground(null);
        }
      }
      return comp;
    }
  }
 
}
